/* * * * M A P V I S I O N   L I C E N S E  *****************************************************************
 *
 * This MapVision software is © Filip Zavadil 2013. It is licensed under the LGPL license.
 * This MapVision software dynamically links to unmodified Qt5 Library.
 *
 * The Qt5 Library is © 2013 Qt® and/or its subsidiary(-ies), and is licensed under the
 * GNU Lesser General Public License version 2.1 with Qt® LGPL exception version 1.1.
 * Qt5 library is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation.
 * Qt5 library is provided “AS IS”, without WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * As an additional permission to the GNU Lesser General Public License version 2.1, the object
 * code form of a “work that uses the Library” may incorporate material from a header file that is
 * part of the Library. You may distribute such object code under terms of your choice,
 * provided that: (i) the header files of the Library have not been modified; and (ii)
 * the incorporated material is limited to numerical parameters, data structure layouts, accessors,
 * macros, inline functions and templates; and (iii) you comply with the terms of Section 6 of the
 * GNU Lesser General Public License version 2.1.
 *
 * Moreover, you may apply this exception to a modified version of the Library, provided that such
 * modification does not involve copying material from the Library into the modified Library’s header
 * files unless such material is limited to (i) numerical parameters; (ii) data structure layouts;
 * (iii) accessors; and (iv) small macros, templates and inline functions of five lines or less in length.
 *
 * Furthermore, you are not required to apply this additional permission to a modified version of the Library.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this package;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

 * The source code for Qt 5.X SDK is available from Qt Project here:
 * http://download.qt-project.org/official_releases/qtcreator/2.7/2.7.0/qt-creator-2.7.0-src.zip.
 *
 * ****************************** M A P V I S I O N    S O F T W A R E  ************************************
 *
 * Author:       Filip Zavadil
 * Description:  Software for displaying and exporting map tiles.
 * The sources and executables of MapVision software are available:
 *    - from project hosting on CodePlex.com :   http://mapvision.codeplex.com
 *    - from GIT repositories on Gitorious.org:  https://gitorious.org/mapvision
 * Visit MapVision fanpage on Facebook.com:      https://www.facebook.com/pages/Mapvision/631827753513935
 *
 * *********************************************************************************************************
*/

#include "layersqlite.h"
#include <QtConcurrent/QtConcurrentRun>


LayerSQLite::LayerSQLite(QMainWindow *mainWindow) : Layer(mainWindow)
{

    dialog = new DialogLayerSQLite(this,this);
    if (dialog->exec()) {
        this->init();
    } else {
        this->deleteLater();
    }
}

LayerSQLite::LayerSQLite(QMainWindow *mainWindow_, Layer::layerType type_, QString name_, QString source_, QPointF lonlat_, int zoom_, int zValue_, int opacity_)
    : Layer(mainWindow_)
{
    setLayerType(type_);
    setLayerName(name_);
    setOrigin(lonlat_,zoom_);
    setOpacity(double(opacity_)/100.0);
    setSource(source_);
    setZvalue(zValue_);
    this->init();

}

void LayerSQLite::init()
{
    getMapScene()->addItem(layerGroup);

    connect(this,SIGNAL(tileIsReady(QString,QPoint,QImage)),
            this,SLOT(tileIsRendering(QString,QPoint,QImage)));

    connect(this,SIGNAL(tileToload(QString,QPoint,QPoint)),
            this,SLOT(tileIsLoad(QString,QPoint,QPoint)));



    // insert item to layer list
    QListWidgetItem *item = new QListWidgetItem(this->getLayerName());
    item->setIcon(QIcon("images/buttons/tilesSQL.svg"));
    item->setCheckState(Qt::Checked);
    item->setData(Qt::UserRole,getId());

    getListWidget()->insertItem(getZvalue(),item);
    setZvalue(this->getListWidget()->count()-1);
    layerGroup->setZValue(getZvalue());

    emit sendMessage("<code>"+tr("Layer ")+this->getLayerName()+tr(" was loaded!")+"</code><br>"  );

    this->connectSQLite(getSource());

    getMapView()->update();
getMapView()->update();
}

void LayerSQLite::connectSQLite(QString source)
{

    database = QSqlDatabase::addDatabase("QSQLITE",source);
    database.setDatabaseName(source);
    if (!database.open()) {
        QMessageBox msgBox;
        msgBox.setText(tr("Database connection cannot be established! "));
        msgBox.exec();
        emit sendMessage(tr("ERROR! Layer: ")+getLayerName()+tr(": Database connection cannot be established! "));
        return;
    } else {
        getMapView()->refresh();
    }

}


QImage LayerSQLite::getTile(QPoint tile, int zoom)
{
    QImage img;

    QSqlQuery *query=new QSqlQuery(database);
    query->exec("SELECT tile_data FROM tiles WHERE tile_column = "+QString::number(tile.x())+" AND tile_row = "+QString::number(tile.y())+" AND zoom_level = "+QString::number(zoom)+";");
    query->first();
    QByteArray byteFileArray=query->value(0).toByteArray();

    img.loadFromData(byteFileArray);

    return img;

}

void LayerSQLite::mapRectChanged(QRect rect, int zoom)
{
    if (isRendering() /*&& database.isOpen()*/){
        int cache=0;
        for (int i=rect.left()-cache;i<=rect.right()+cache;i++){
            for (int j=rect.bottom()-cache;j<=rect.top()+cache;j++){
                QPoint position = zavaProj.pointForTile(QPoint(i,j),zoom);

                QString key = getSource()+"&z="+QString::number(zoom)+"&x="+QString::number(i)+"&y="+QString::number(j);

                if (!sources.contains(key)){
                    if (renderingType == CONCURRENT){
                        QtConcurrent::run(this,&LayerSQLite::tileIsLoadingConCurent, key, QPoint(i,j) ,position);
                    } else if (renderingType == CURRENT){
                        tileIsLoadingConCurent(key,QPoint(i,j),position);
                    } else {
                        if (rect.width()>6) QtConcurrent::run(this,&LayerSQLite::tileIsLoadingConCurent, key,QPoint(i,j), position);
                        else tileIsLoadingConCurent(key,QPoint(i,j),position);
                    }
                    sources << key;
                }
            }
        }
    }
}

void LayerSQLite::tileIsLoadingConCurent(QString source,QPoint tile, QPoint pos)
{
    emit tileToload(source,tile,pos);
}


void LayerSQLite::tileIsRendering(QString source, QPoint pos, QImage img)
{
    QGraphicsPixmapItem * tile = new QGraphicsPixmapItem(QPixmap::fromImage(img));
    tile->moveBy(pos.x(),pos.y());
    tile->setData(Qt::UserRole,getLayerName());
    layerGroup->addToGroup(tile);
    items.insert(source,tile);
}

void LayerSQLite::tileIsLoad(QString source, QPoint tileFormat, QPoint pos)
{
    QImage tile = getTile(tileFormat,getMapView()->getZoom());
    emit tileIsReady(source,pos,tile);

}

